package ModelAndController;
/*
 * Az ütemező osztály, felelős az ütemezési ciklusért, 
 * azaz a megfelelő huzalok és hálózati elemek állapotfrissítésének elindításáért, 
 * valamint a stabil állapot detektálásáért.
 */
//Exception 260 es 279 kozott
public class Scheduler {
	//referencia az építőelemekre.
	CircuitElements circuitElements;
	/*
	 * A maximális frissítések száma. Ha az isUpdatesResultStableCircuit() 
	 * nem éri el ennyi cikluslépés alatt a hálózat stabil állapotát, 
	 * akkor visszatér és jelzi ezt a visszatérési értéken.
	 */
	private int nbOfMaxUpdates;
	//az osztály kimeneti üzeneteit gyűjtő tömb
	private String buffer;
	//tabulátor karaktert tároló string
	private String tab;
	// soremelés karaktert tároló string
	private String newLine;
	//konstruktor
	public Scheduler(CircuitElements cE){
		circuitElements=cE;
		tab = "     ";
		newLine = System.getProperty("line.separator");
	}
	/*
	 * Az ütemező loopját valósítja meg, ami meghívja a circuitElements osztály 
	 * updateAllElements() és updateAllWires() metódusait. Az ütemezési ciklus 
	 * a SignalGenerator-ok soron következő belső állapotának beállításával kezdődik.
	 */
	public boolean isUpdateResultStableCircuit(boolean shouldListDetails, int[] compositeShouldWriteDetailsOutput) throws Exception{
		try{
			buffer = "";
		
			//Beallitjuk, hogy melyik Compositeok irjanak reszletes infokat.
			if( shouldListDetails ){
				circuitElements.setCompositesIfShouldWriteDetails(compositeShouldWriteDetailsOutput);
				buffer = "@ Schedule "+circuitElements.getNbOfCircuitElements()+newLine+newLine;
			}
		
			//Kapcsolo es jelgenerator utemezesi engedely
			circuitElements.setNextStateAtSignalGenerators();
			circuitElements.signalGeneratorsAndSwitchesUpdateToSchedule();
			circuitElements.clearScopesDelta();
		
			for (int i = 0; i < nbOfMaxUpdates; i++)
				if( updateLoops(i, shouldListDetails)){
					if( !shouldListDetails ){
						circuitElements.updateAllElements();
						buffer = "Circuit reached stable state:"+newLine+circuitElements.getBuffer().replaceFirst(tab, "");
					}
					circuitElements.finalizeScopes();
					circuitElements.allCompositeStopListingDetails();
					return true;
				}
		
			//Nem sikerult stabil allapotot elerni, buffer felulirasa es false return
			circuitElements.allCompositeStopListingDetails();
			buffer = buffer.concat("Circuit didn't reach stable state!"+newLine);
			if(circuitElements.getNbOfCircuitElements() == 0)
				throw new Exception("260  At circuitNb="+circuitElements.getNbOfCircuitElements()+" "+buffer);
			else
				throw new Exception("260 At Composite, circuitNb="+circuitElements.getNbOfCircuitElements()+" "+buffer);
		}
		catch(Exception e){
			circuitElements.allCompositeStopListingDetails();
			if(e.getMessage().startsWith("260"))
				throw new Exception(260+" "+newLine+buffer+" "+e.getMessage().replaceFirst("260", ""));
			throw e;
		}
	}
	//ütemezési ciklus futtatása
	private boolean updateLoops(int i, boolean shouldListDetails) throws Exception{

		if( shouldListDetails )
			buffer = buffer.concat(tab+"@LOOP="+i+newLine);
		
		boolean ret1=circuitElements.updateAllElements();
		
		if( shouldListDetails )
			buffer = buffer.concat( circuitElements.getBuffer()+newLine );
		
		boolean ret2=circuitElements.updateAllWires();
		
		if( shouldListDetails )
			buffer = buffer.concat( circuitElements.getBuffer()+newLine );
		
		//Stabil allapot
		if(ret1==false && ret2==false){
			if(shouldListDetails)
				buffer = buffer.concat(newLine+"@End Scedule "+circuitElements.getNbOfCircuitElements());
			return true;
		}
		
		if( shouldListDetails )
			buffer = buffer.concat(newLine);
		
		return false;
	}
	//Beállítja a maximális frissítések számát.
	public void setNbOfMaxUpdates(int cycles){
		nbOfMaxUpdates=cycles;
	}

	/*
	 * @return the buffer
	 */
	public String getBuffer() {
		return buffer;
	}

	/*
	 * @param buffer beállítása
	 */
	public void setBuffer(String buffer) {
		this.buffer = buffer;
	}
}
